package mammuthus.controller.app

import mammuthus.slave.InteractiveShellCommand
import mammuthus.tool.{TemplateTool, Constants}
import net.csdn.modules.http.{ViewType, RestRequest, ApplicationController}
import net.csdn.annotation.rest.{State, BasicInfo, At}
import com.google.inject.Inject
import mammuthus.master.Master
import net.liftweb.{json => SJSon}
import net.csdn.common.env.Environment

import scala.io.Source
import mammuthus.controller.filter.{AppNameCheckFilter, TokenAuthFilter}

/**
 * 2/2/15 WilliamZhu(allwefantasy@gmail.com)
 */
class AppInstallTaskController @Inject()(akkaMaster: Master, env: Environment) extends ApplicationController with TokenAuthFilter with AppNameCheckFilter{
  implicit val formats = SJSon.Serialization.formats(SJSon.NoTypeHints)

  val appRootDir = Constants.getAppRootDir

  def appName = param("appName")


  @At(path = Array("/app/config"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "生成app配置",
    state = State.alpha,
    testParams = "?" +
      "installPath=/data/1/usr/local&" +
      "appName=zookeeper&app=zookeeper",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appConfig = {
    auth
    if (isEmpty(param("slaves")) || isEmpty(param("installPath")) || isEmpty(param("appName"))) {
      render(400, "slaves,installPath,appName should not be null")
    }
    checkAppName
    import scala.collection.JavaConversions._

    val res = akkaMaster.configApp(getAppHostsByAppName, params().toMap)
    render(SJSon.Serialization.write(res), ViewType.json)
  }

  private def getAppHostsByAppName = {
    val appList = akkaMaster.appList
    if (!appList.contains(appName)) render(400, s"$appName is not installed")
    param("slaves", appList(appName).mkString(","))
  }


  @At(path = Array("/app/install"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "安装app",
    state = State.alpha,
    testParams = "" +
      "slaves=allwefantasy&" +
      "url=http://127.0.0.1:9003/zookeeper-3.4.6.tar.gz&" +
      "filePath=/data/1/usr/local/softwares/zookeeper-3.4.6.tar.gz&" +
      "installPath=/data/1/usr/local&" +
      "appName=zookeeper",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appInstall = {
    auth
    if (isEmpty(param("slaves")) || isEmpty(param("installPath")) || isEmpty(param("url"))
      || isEmpty(param("filePath")) || isEmpty(param("appVersion"))
      || isEmpty(param("appName"))) {
      render(400, "slaves,url,filePath,installPath,appName,appVersion should not be null")
    }
    checkAppName

    import scala.collection.JavaConversions._
    val shellResps = akkaMaster.installApp(param("slaves"), params.toMap)
    render(SJSon.Serialization.write(shellResps), ViewType.json)


  }


  @At(path = Array("/app/control"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "对安装的应用进行 启动，停止，重启，询问状态等动作",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appControl = {
    auth
    if (isEmpty(param("appName"))) render(400, "appName is required")
    if (isEmpty(param("command"))) render(400, "command is required start|status|stop|restart")
    val appName = param("appName")
    val command = param("command")
    val appList = akkaMaster.appList

    if (param("appType") != "default" && !appList.contains(param("appName"))) render(400, s"${param("appName")} 不存在")

    val shell = if (param("appType") == "default") {

      if (hasParam("moduleFile") && !param("moduleFile").isEmpty) {

        akkaMaster.writeFile(param("slaves"),
          Source.fromFile(env.templateDirFile().getPath + "/command/shell/app.sh").getLines.mkString("\n"), s"${appRootDir}$appName/app.sh", false)

        TemplateTool.render("/template/command/shell/app_sh/appWithModule.vm", Map(
          "app" -> s"${appRootDir}$appName",
          "moduleFile" -> param("moduleFile"),
          "command" -> command
        ))

      } else {
        TemplateTool.render("/template/command/shell/app_sh/app.vm", Map(
          "app" -> s"${appRootDir}$appName",
          "command" -> command
        ))
      }

    } else
      s"${appRootDir}$appName/control.sh $command"


    val list = appList

    logger.info("shell " + shell)
    val res = if (paramAsBoolean("block", false) == true)
      akkaMaster.executeBlockShellCommand(param("slaves", if (appList.contains(appName)) list(appName).mkString(",") else ""), shell)
    else
      akkaMaster.executeShellCommand(param("slaves", if (appList.contains(appName)) list(appName).mkString(",") else ""), shell, paramAsLong("tt", InteractiveShellCommand.defaultTimeOut))



    render(SJSon.Serialization.write(res), ViewType.json)

  }


  @At(path = Array("/conf/control"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "激活mammuthus-conf系统",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def mammuthusConfControl = {
    auth
    val res = akkaMaster.startMammuthusConf(param("slaves", akkaMaster.slaves.keys.mkString(",")))
    render(SJSon.Serialization.write(res), ViewType.json)

  }




}
